package net.goodapp.util;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;

import net.goodapp.MainClass;
import net.goodapp.model.TableInfo;

public class JavaGenerator {
	private static final Log logger = LogFactory.getLog(JavaGenerator.class);
	private List<TableInfo> tableInfos;
	private VelocityEngine velocityEngine;
	private VelocityContext context;
	private Charset charset=Charset.forName(MainClass.UTF8ENCODING);

	public JavaGenerator(List<TableInfo> tableInfos) {
		this.tableInfos = tableInfos;
	}

	public void initVelocity() {
		
		Properties projectProperties = new Properties();
		
		try {
			// 配置文件和当前类的class放在一起
			projectProperties.load(this.getClass().getClassLoader().getResourceAsStream("projectConfig.properties"));
		} catch (IOException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		
		Properties velocityProperties = new Properties();
		velocityProperties.put("file.resource.loader.class",
				"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		//设置velocity的输入输出为utf-8编码，以防出现乱码
		velocityProperties.put(Velocity.ENCODING_DEFAULT, MainClass.UTF8ENCODING);
		velocityProperties.put(Velocity.INPUT_ENCODING, MainClass.UTF8ENCODING);
		velocityProperties.put(Velocity.OUTPUT_ENCODING, MainClass.UTF8ENCODING); 

		// 初始化并取得Velocity引擎
		velocityEngine = new VelocityEngine();
		velocityEngine.init(velocityProperties);
		// 取得velocity的模版
		// Template template = velocityEngine.getTemplate("databaseConfig.vm");
		// 取得velocity的上下文context
		context = new VelocityContext();
		// logger.info("put "+tableInfos.size()+" tables in context");
		// System.out.println("put "+tableInfos.size()+" tables in context");
		// 把数据填入上下文
		//context.put("tableInfos", tableInfos);
		
		context.put("nc", NamingConventions.class);
		context.put("javaModelPackageName", projectProperties.getProperty("javaModelPackageName"));
		context.put("javaDAOPackageName", projectProperties.getProperty("javaDAOPackageName"));
		context.put("javaServicePackageName", projectProperties.getProperty("javaServicePackageName"));
		context.put("javaServicelImplPackageName", projectProperties.getProperty("javaServicelImplPackageName"));
	}

	/**
	 * 根据指定模板生成POJO类
	 */
	public void generateModel() {
		// 取得velocity的模版
		Template template = velocityEngine.getTemplate("javaModelConfig.vm");
		
		StringWriter writer=null;
		File file=null;
		for (TableInfo tableInfo : tableInfos) {
			if(tableInfo.isIgnored()){
				continue;
			}
			if(context.containsKey("table")){
				context.remove("table");
			}
			context.put("table", tableInfo);
			
			writer=new StringWriter();
			template.merge(context, writer);
			try {
				file = new File(tableInfo.getEntityName()+".java");
				logger.info("generated "+tableInfo.getEntityName()+".java.");
				FileUtils.writeStringToFile(file, writer.toString(), charset, false);
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
	}

	/**
	 * 根据模板生成DAO(Data Access Object)类
	 */
	public void generateDAO() {
		// 取得velocity的模版
		Template template = velocityEngine.getTemplate("javaDAOConfig.vm");

		StringWriter writer = null;
		File file = null;
		for (TableInfo tableInfo : tableInfos) {
			if(tableInfo.isIgnored()){
				continue;
			}
			if (context.containsKey("table")) {
				context.remove("table");
			}
			context.put("table", tableInfo);

			writer = new StringWriter();
			template.merge(context, writer);
			try {
				file = new File(tableInfo.getEntityName() + "DAO.java");
				logger.info("generated " + tableInfo.getEntityName() + "DAO.java.");
				FileUtils.writeStringToFile(file, writer.toString(), charset, false);
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
	}

	/**
	 * 根据模板生成Service类（用于指定规范）
	 */
	public void generateService() {
		// 取得velocity的模版
		Template template = velocityEngine.getTemplate("javaServiceConfig.vm");

		StringWriter writer = null;
		File file = null;
		for (TableInfo tableInfo : tableInfos) {
			if(tableInfo.isIgnored()){
				continue;
			}
			if (context.containsKey("table")) {
				context.remove("table");
			}
			context.put("table", tableInfo);

			writer = new StringWriter();
			template.merge(context, writer);
			try {
				file = new File(tableInfo.getEntityName() + "Service.java");
				logger.info("generated " + tableInfo.getEntityName() + "Service.java.");
				FileUtils.writeStringToFile(file, writer.toString(), charset, false);
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
	}

	/**
	 * 根据模板生成ServiceImpl类（用于具体实现）
	 */
	public void generateServiceImpl() {
		// 取得velocity的模版
		Template template = velocityEngine.getTemplate("javaServiceImplConfig.vm");

		StringWriter writer = null;
		File file = null;
		//Charset charset = Charset.forName("UTF-8");
		for (TableInfo tableInfo : tableInfos) {
			if(tableInfo.isIgnored()){
				continue;
			}
			if (context.containsKey("table")) {
				context.remove("table");
			}
			context.put("table", tableInfo);

			writer = new StringWriter();
			template.merge(context, writer);
			try {
				file = new File(tableInfo.getEntityName() + "ServiceImpl.java");
				logger.info("generated " + tableInfo.getEntityName() + "ServiceImpl.java.");
				FileUtils.writeStringToFile(file, writer.toString(), charset, false);
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
	}

	/**
	 * 根据模板生成适合于MyBatis的XML映射文件
	 */
	public void generateMyBatisXMLMapper() {
		// 取得velocity的模版
		Template template = velocityEngine.getTemplate("javaXMLMapperConfig.vm");

		StringWriter writer = null;
		File file = null;
		//Charset charset = Charset.forName("UTF-8");
		for (TableInfo tableInfo : tableInfos) {
			if(tableInfo.isIgnored()){
				continue;
			}
			if (context.containsKey("table")) {
				context.remove("table");
			}
			context.put("table", tableInfo);

			writer = new StringWriter();
			template.merge(context, writer);
			try {
				file = new File(tableInfo.getEntityName() + "Mapper.xml");
				logger.info("generated " + tableInfo.getEntityName() + "Mapper.xml.");
				FileUtils.writeStringToFile(file, writer.toString(), charset, false);
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
	}
	
	/**
	 * 根据模板生成适合于MyBatis的Java注射式映射文件
	 */
	public void generateMyBatisClassMapper() {

	}
}
